<template>
	<view class="warp">
		<view class="search">
			<view class="searchInput" @click="gotoSearch()">
				<u-icon name="search" color="#909399" :size="26"></u-icon>
				<text class="inputTxt">请输入搜索关键词</text>
			</view>
		</view>
		<!-- 加载效果 -->
		<block v-if="status == 'loading'">
			<u-loadmore :status="status"></u-loadmore>
		</block>
		<!-- 滚动区域 -->
		<view v-else-if="status == 'nomore'" class="menuwrap">
			<!-- 左侧滚动区域 ：纵向滚动；开启滑动的动画效果-->
			<scroll-view scroll-y scroll-with-animation class="leftNav" :scroll-top="scrollTop">
				<view v-for="(item , index) in navList" :key="item.name" class="tabItem" @tap.stop='toggleMenu(index)'>
					<text :class="['line', currentIndex==index?'active':'' ]">{{item.name}}</text>
				</view>
			</scroll-view>
			
			<!-- 右侧滚动区域，纵向滚动，开启滑动的动画效果 动态设置纵向滚动条在每次点击后的位置-->
			<scroll-view scroll-y scroll-with-animation class="rightNav" @scroll="rightScroll" :scroll-top="scrollRightTop">
				<view class="pageView">
					<view class="section" v-for="(item, index) in navList" :key="item.name" :id="'item'+index">
						<view class="title">
							<text>{{item.name}}</text>
						</view>
						<view class="aside">
							<!-- key不可重复 -->
							<view class="li" v-for="(val,i) in item.foods" :key="i">
								<image class="li-img" :src="val.icon"></image>
								<view class="li-name">{{val.name}}</view>
							</view>
						</view>
					</view>
				</view>
			</scroll-view>
		</view>
	</view>
</template>

<script>
	import {apiClassfy} from '../../api/mock'
	export default {
		data() {
			return {
				navList:[], //分类数据
				status:'loading',
				scrollTop:0 ,//每次点击的滚动条位置变量，默认从第一个开始
				oldScrollTop:0, //上一次点击的滚动条位置
				menuHeight:0, //整个左侧菜单的高度
				menuTtemHeight:0, //左侧单个菜单的高度
				currentIndex:0,
				TopArr :[], //根据标签顺序，获取每个section的高度
				scrollRightTop:0,
				timer:''
			}
			
		},
		onLoad() {
			this.getClassfy();
		},
		onReady() {
			//当页面初次渲染完成后，获取所有section的高度（右侧菜单的所有高度）
			this.getMenuItemTopDistance();
		},
		methods: {
			gotoSearch(){
				uni.navigateTo({
					url:'/pagesB/search/search'
				})
			},
			getClassfy(){
				apiClassfy().then((res)=>{
					this.status = 'nomore';
					this.navList = [...res];
				}).catch((err)=>{
					console.log(err);
				})
			},
			/*工具函数：获取右侧每个子菜单的高度（到顶部的距离）*/
			getMenuItemTopDistance(){
				new Promise((resolve)=>{
					let query = uni.createSelectorQuery();
					//从所有section中获取每个节点的布局位置信息
					query.selectAll('.section').boundingClientRect((data)=>{
						if(!data.length){
							setTimeout(()=>{
								this.getMenuItemTopDistance();
								return;
							},20)
						}
						//遍历：获取每个section的top坐标，计算出距离第一个置顶的菜单距离
						data.forEach((item)=>{
							this.TopArr.push(item.top - data[0].top);
							resolve();
						})
					}).exec();
				})
			},
			/*工具函数：获取左侧菜单的整体高度以及单个标签的高度（标签设置为参数：为了让toggleMenu做菜单定位剧中）*/
			/*elClass:你想要获取的 标签选择器名称*/
			/*dataVal参数：动态给个不确定的data变量赋值*/
			
			getElRect(elClass, dataVal){
				new Promise((resolve,reject)=>{
					let query = uni.createSelectorQuery().in(this);
					//获取指定标签选择器中的尺寸宽高
					query.select('.'+elClass).fields({size:true},(res)=>{
						//如果页面渲染加载较慢，有可能标签在此时仍未获取成功
						if(!res){
							setTimeout(()=>{
								//过一段时间再次执行本函数即可
								this.getElRect(elClass);
							},20)
							return;
						}
						//将this作为数组；将dataVal作为下标：根据需求：从res内提取所有所需信息
						this[dataVal] = res.height; //this.menuItemHeight = 55；
						console.log(this[dataVal]);
					}).exec();
				})
			},
			/*切换左侧菜单，促使被点击的菜单居中显示（抛出最开始和最后的菜单）*/
			async toggleMenu(index){
				//保险机制
				// if(this.TopArr.length == 0){
				// 	//保险机制：当前事件调用之前，像判断工具函数的返回值/data数据是否已经有结果，如果没有结果，那就需要再次执行工具函数
				// 	await this.getMenuItemTopDistance();
				// }
				// 判断：当前点击的菜单下标跟当前循环的菜单下标是否一致：赋值
				//重复点击
				if(index == this.currentIndex) return;
				//将上一次获取到的滚动条位置赋值给右侧滚动变量
				this.scrollRightTop = this.oldScrollTop;
				console.log(this.oldScrollTop);
				//this.$nextTick()：将Dom更新时机；下一次数据更新之后，Dom更新之前
				this.$nextTick(function(){
					//将本次点击的下标index，从section高度数组中获取对应的元素并赋值给右侧滚动高度
					this.scrollRightTop = this.TopArr[index];
					//将本次点击的下标赋值给下一个选中下标变量
					this.currentIndex = index;
					this.leftMenuStatic(index);
				})
				//将当前被点击的菜单相关选择器传递过去
			},
			//设置左侧菜单的滚动动画状态：居中菜单
			async leftMenuStatic( index ){
				//将本次电机的下标，赋值给当前选择器样式判断变量
				this.currentIndex = index;
				//如果两个菜单高度都为0的情况下，表示菜单的高度并未获取
				if(this.menuHeight == 0 || this.menuTtemHeight == 0){
					//获取整个左侧菜单的高度
					await this.getElRect('leftNav','menuHeight');
					//获取单个菜单的高度
					await this.getElRect('tabItem','menuTtemHeight')
				}
				console.log(index, this.menuHeight, this.menuTtemHeight);
				//计算出当前所点击的菜单，需要将滚动条设置到哪个位置上
				this.scrollTop = index*this.menuTtemHeight + this.menuTtemHeight/2-this.menuHeight/2;
				console.log(this.scrollTop);
			},
			async rightScroll(e){
				
				//将本次的滚动顶点坐标赋值给oldScrollTop
				this.oldScrollTop =e.detail.scrollTop;
				//保险机制：当前事件调用之前，像判断工具函数的返回值/data数据是否已经有结果，如果没有结果，那就需要再次执行工具函数
				if(this.TopArr.length == 0){
					await this.getMenuItemTopDistance();
				}
				if( !this.menuHeight ){
					await this.getElRect('leftNav','menuHeight');
				}
				//定时器：节流
				this.timer = setTimeout(()=>{
					//延时定时器启动后，内部清空
					this.timer = null;
					//计算出右侧菜单垂直中心点的位置
					let scrollHeight = this.menuHeight/2 + e.detail.scrollTop;
					//遍历所有section的高度
					for(let i=0; i<this.TopArr.length; i++){
						let height1 = this.TopArr[i]; //当前i的高度
						let height2 = this.TopArr[i+1]; //下一个i的高度 美食section
						//还没到最后一个section 或则 滚动的中间点大于当前section的高度（滚动已经离开了当前菜单）同时 滚动的中间点小于下一个菜单（下一个菜单还没滚完）
						if(!height2 || scrollHeight>=height1 && scrollHeight < height2){
							this.leftMenuStatic(i);
							return;
						}
					}
				},100)
			}
		}
	}
</script>

<style lang="scss">
	/*calc():计算复杂公式：计算设备屏幕尺寸计算出目标区域的自适应高度*/
	.warp{
		height: calc(93vh);
		display: flex;
		flex-direction: column;
		/*#ifdef H5*/
		height: calc(100vh - var(--window-top));
		/*#endif*/
	}
	/*搜索框样式*/
	.search{
		padding: 0px 20px;
		.searchInput{
			background-color: rgb(234, 234, 234);
			border-radius: 20px;
			display: flex;
			align-items: center;
			padding: 0 8px;
			.inputTxt{
				font-size: 14px;
				color: $u-tips-color;
				margin-left: 10px;
			}
		}
	}
	.menuwrap{
		background-color: white;
		display: flex;
		flex:1; //表示：在100vh基础下，减去搜索框所占的高度，剩余高度由该标签继承
		overflow: hidden;
		// 左侧
		.leftNav{
			width: 25%;
			//高度100%的前提是：父级标签有明确高度；100%与父级标签高度一致【父级标签没有高度是设置高度百分百相当于没有高度】
			height: 100%;
			
			.tabItem{
				height: 55px;
				background-color: #f6f6f6;
				box-sizing: border-box;
				font-size: 13px;
				color: #444;
				font-weight: 400;
				.line{
					display: flex;
					justify-content: center;
					align-items: center;
					width: 100%;
					height: 100%;
					&.active{
						/*&表示当前所在区域的class选择器。tabitem*/
						color: #000;
						font-size: 15px;
						font-weight: 600;
						background-color: white;
						position: relative;
						
						// ::before伪类：在指定标签之前添加标签效果（不用标签包裹的）
						//::after伪类：在指定标签之后添加的效果
						&::before{
							content: "";
							position: absolute;
							height: 16px;
							left: 0;
							top: calc((55-16)/2);
							border: 2px solid #3c9cff;
						}
					}
				}
			}
		}
	}
	.rightNav{
		
		.pageView{
			padding: 8px;
			overflow: hidden;
			.section{
				margin-bottom: 15px;
				padding: 8px;
				border-radius: 4px;
				&:last-child{
					min-height: 100vh;
				}
				.title{
					font-size: 14px;
					color: #303133;
					font-weight: bold;
				}
				.aside{
					display: flex;
					flex-wrap: wrap;
					.li{
						width: 33.33333%;
						display: flex;
						align-items: center;
						justify-content: center;
						flex-direction: column;
						margin-top: 10px;
						.li-img{
							width: 60px;
							height: 60px;
						}
						.li-name{
							font-weight: normal;
							font-size: 12px;
							color: #303133;
						}
					}
				}
			}
		}
	}
</style>
